/**
 * 雨量计算算法模块
 * 提供水文计算中与暴雨、洪水相关的各类计算功能
 * 包括暴雨指数、洪峰流量、造峰影响雨量、点面系数等核心算法
 */
export class RainfallAlgorithms {
  /**
   * 计算暴雨指数
   * 基于汇水面积计算暴雨衰减特性的指数参数
   * 用于后续洪峰流量计算公式
   * 
   * @param {number} F 汇水面积(km²)
   * @returns {number} 暴雨指数(β)
   */
  static stormIndex(F: number): number {
    // 计算暴雨指数: β = 1.68 × (F + 0.5)^(-0.035)
    const beta = 1.68 * Math.pow(F + 0.5, -0.035);
    return beta;
  }

  /**
   * 计算洪峰流量
   * 基于综合影响系数、造峰影响雨量和暴雨指数计算最大洪峰流量
   * 
   * @param {number} K 综合影响系数
   * @param {number} H_r 造峰影响雨量(mm)
   * @param {number} beta 暴雨指数
   * @returns {number} 洪峰流量(m³/s)
   */
  static peakFloodFlow(K: number, H_r: number, beta: number): number {
    // 计算洪峰流量: Q = K × H_r^β
    const Q = K * Math.pow(H_r, beta);
    return Q;
  }

  /**
   * 计算造峰影响雨量
   * 考虑面雨量、造峰历时、设计历时、暴雨参数和递减指数等因素
   * 
   * @param {number} H_Ft 面雨量(mm)
   * @param {number} T 造峰历时(h)
   * @param {number} t 设计历时(h)
   * @param {number} d 暴雨参数
   * @param {number} n 暴雨递减指数
   * @returns {number} 造峰影响雨量(mm)
   */
  static peakRainfallHr(H_Ft: number, T: number, t: number, d: number, n: number): number {
    // 计算造峰影响雨量: H_T = H_Ft × T/t × [(t+d)/(T+d)]^n
    const H_T = H_Ft * T / t * Math.pow((t + d) / (T + d), n);
    return H_T;
  }

  /**
   * 计算坡降影响系数
   * 基于河道平均坡降计算对洪水流量的影响系数
   * 
   * @param {number} J 计算断面以上河道平均坡降(%o)
   * @returns {number} 坡降影响系数(K2)
   */
  static slopeK2(J: number): number {
    // 计算坡降影响系数: K2 = 0.07 × ln(J) + 0.75
    const K2 = 0.07 * Math.log(J) + 0.75;
    return K2;
  }

  /**
   * 计算汇水面积影响系数
   * 根据不同的汇水面积范围使用不同的计算公式
   * 特殊情况考虑河道坡降的影响
   * 
   * @param {number} F 计算断面以上汇水面积(km²)
   * @param {number} [J] 计算断面以上河道平均坡降(%o)，可选参数，用于特殊情况计算
   * @returns {number} 汇水面积影响系数(K1)
   * @throws {Error} 当汇水面积超出适用范围时抛出错误
   */
  static drainageAreaK1(F: number, J?: number): number {
    let K1: number;
    
    // 特殊情况：当F≤5km²且主河道平均坡降J>50%o时
    if (F <= 5 && J !== undefined && J > 50) {
      K1 = 0.0013 * Math.pow(F, 2) - 0.0174 * F + 1.0744;
    }
    // 情况1：当0.0<F≤20km²时
    else if (0 < F && F <= 20) {
      K1 = -0.0002 * Math.pow(F, 2) + 0.0105 * F + 0.971;
    }
    // 情况2：当20km²<F≤100km²时
    else if (20 < F && F <= 100) {
      K1 = 0.1705 * Math.log(F) + 0.4829;
    }
    // 情况3：当100km²<F≤1000km²时
    else if (100 < F && F <= 1000) {
      K1 = -0.086 * Math.log(F) + 1.6513;
    }
    // 超出适用范围
    else {
      throw new Error("汇水面积超出适用范围");
    }
    
    return K1;
  }

  /**
   * 根据汇水面积选择设计历时
   * 设计历时是水文计算中的重要参数，根据汇水面积大小确定
   * 
   * @param {number} F 汇水面积(km²)
   * @returns {number} 设计历时(h)
   * @throws {Error} 当汇水面积超出适用范围时抛出错误
   */
  static designDurationT(F: number): number {
    let t: number;
    
    // 汇水面积不同范围对应不同设计历时
    if (0 < F && F <= 20) {
      t = 6; // 6小时
    } else if (20 < F && F <= 100) {
      t = 12; // 12小时
    } else if (100 < F && F <= 1000) {
      t = 24; // 24小时
    } else {
      throw new Error("汇水面积超出适用范围");
    }
    
    return t;
  }

  /**
   * 计算12小时点暴雨量
   * 通过6小时和24小时点暴雨量，使用暴雨衰减指数法计算
   * 
   * @param {number} H6 6小时点暴雨量(mm)
   * @param {number} H24 24小时点暴雨量(mm)
   * @returns {number} 12小时点暴雨量(mm)
   */
  static pointRainfall12(H6: number, H24: number): number {
    // 计算暴雨衰减指数: γ = 1 + 0.721 × log10(H6/H24)
    const gamma = 1 + 0.721 * Math.log10(H6 / H24);
    
    // 计算12小时点暴雨量: H12 = H24 × 24^(γ-1) × 12^(1-γ)
    const H12 = H24 * Math.pow(24, gamma - 1) * Math.pow(12, 1 - gamma);
    
    return H12;
  }

  /**
   * 计算面雨量
   * 通过点暴雨量和点面系数转换计算面雨量
   * 
   * @param {number} Ht 点暴雨量(mm)
   * @param {number} alpha_t 点面系数
   * @returns {number} 面雨量(mm)
   */
  static areaRainfall(Ht: number, alpha_t: number): number {
    // 计算面雨量: H_Ft = α_t × H_t
    const HFt = alpha_t * Ht;
    return HFt;
  }

  /**
   * 计算24小时点面系数
   * 根据汇水面积和水文气象分区计算
   * 支持第Ⅴ区、第Ⅶ区、第Ⅷ区、第Ⅹ区
   * 
   * @param {number} F 汇水面积(km²)
   * @param {number} zone 水文气象分区(7, 8, 10, 5)
   * @returns {number} 24小时点面系数(α_24)
   * @throws {Error} 当水文气象分区不支持时抛出错误
   */
  static pointAreaCoefficient24(F: number, zone: number): number {
    let a: number, b: number;
    
    // 根据水文气象分区选择系数a和b
    if ([7, 10].includes(zone)) {  // 第Ⅶ区、第Ⅹ区
      a = 0.17;
      b = 0.0083;
    } else if ([8, 5].includes(zone)) {  // 第Ⅷ区、第Ⅴ区
      a = 0.168;
      b = 0.0054;
    } else {
      throw new Error("不支持的水文气象分区");
    }

    // 计算24小时点面系数: α_24 = (1 + b×F)^(-a)
    const alpha_24 = Math.pow(1 + b * F, -a);
    return alpha_24;
  }

  /**
   * 计算12小时点面系数
   * 基于24小时点面系数和汇水面积计算
   * 
   * @param {number} F 汇水面积(km²)
   * @param {number} alpha_24 24小时点面系数
   * @returns {number} 12小时点面系数(α_12)
   */
  static pointAreaCoefficient12(F: number, alpha_24: number): number {
    // 计算12小时点面系数: α_12 = α_24 × (4e-8×F² - 9.028e-5×F + 0.9979)
    const alpha_12 = alpha_24 * (4e-8 * Math.pow(F, 2) - 9.028e-5 * F + 0.9979);
    return alpha_12;
  }

  /**
   * 计算6小时点面系数
   * 基于24小时点面系数和汇水面积计算
   * 
   * @param {number} F 汇水面积(km²)
   * @param {number} alpha_24 24小时点面系数
   * @returns {number} 6小时点面系数(α_6)
   */
  static pointAreaCoefficient6(F: number, alpha_24: number): number {
    // 计算6小时点面系数: α_6 = α_24 × (-1.8e-10×F³ + 3.621e-7×F² - 2.88e-4×F + 0.9965)
    const alpha_6 = alpha_24 * (-1.8e-10 * Math.pow(F, 3) + 3.621e-7 * Math.pow(F, 2) - 2.88e-4 * F + 0.9965);
    return alpha_6;
  }

  /**
   * 根据设计历时选择暴雨参数d
   * 不同设计历时对应不同的暴雨参数
   * 
   * @param {number} t 设计历时(h)
   * @returns {number} 暴雨参数(d)
   * @throws {Error} 当设计历时不支持时抛出错误
   */
  static selectStormParameterD(t: number): number {
    let d: number;
    
    // 根据设计历时选择相应的暴雨参数
    if (t === 6) {
      d = 0.1;
    } else if (t === 12) {
      d = 0.15;
    } else if (t === 24) {
      d = 0.2;
    } else {
      throw new Error("不支持的设计历时");
    }
    
    return d;
  }

  /**
   * 计算所有雨量相关参数
   * 整合上述所有计算方法，提供完整的雨量计算解决方案
   * 
   * @param {Object} params 计算参数对象
   * @returns {Object} 包含所有计算结果的对象
   */
  static calculateAllRainfall(params: any): any {
    // 这里将在实际实现时整合所有计算方法
    // 返回完整的计算结果集合
    return {};
  }
}